Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 16 Die wichtigsten Steuerelemente
  gp 16.1 Gemeinsame Eigenschaften, Methoden und Ereignisse
    gp 16.1.1 Größe und Position
    gp 16.1.2 Die Sichtbarkeit und der Aktivierungszustand
    gp 16.1.3 Die Eigenschaft »Text«
    gp 16.1.4 Die Farbeigenschaften
    gp 16.1.5 Grafische Darstellung
    gp 16.1.6 Die »Modifiers«-Eigenschaft
    gp 16.1.7 Die Eigenschaft »Tag«
    gp 16.1.8 Die Größe von Steuerelementen dynamisch der Formgröße anpassen
    gp 16.1.9 Die »Dock«-Eigenschaft
    gp 16.1.10 Die z-Reihenfolge
    gp 16.1.11 Die Tabulatorreihenfolge
    gp 16.1.12 Steuerelemente fokussieren
    gp 16.1.13 Maus- und Tastaturereignisse
  gp 16.2 Schaltflächen der Klasse »Button«
    gp 16.2.1 Die Rahmendarstellung einer Schaltfläche
    gp 16.2.2 Die Eigenschaft »FlatAppearance«
    gp 16.2.3 Beschriftung und Grafiken
    gp 16.2.4 Weitere Gestaltungsmöglichkeiten
  gp 16.3 Auswahlkästchen mit der Klasse »CheckBox«
    gp 16.3.1 Eigenschaften eines Kontrollkästchens
    gp 16.3.2 Checkboxen mit drei Aktivierungszuständen
  gp 16.4 Die Klasse »RadioButton« (Optionsschaltflächen)
    gp 16.4.1 Die Gruppierung der Optionsschaltflächen
    gp 16.4.2 Die Eigenschaften von Optionsschaltflächen
    gp 16.4.3 Den Zustandswechsel programmieren
  gp 16.5 Die »GroupBox« als übergeordneter Container
  gp 16.6 Texteingabefelder mit der Klasse »TextBox«
    gp 16.6.1 Einzeilige Eingabefelder
    gp 16.6.2 Mehrzeilige Eingabefelder
  gp 16.7 Das Steuerelement »RichTextBox«
  gp 16.8 Beschriftungen mit dem Steuerelement »Label«
  gp 16.9 Das »LinkLabel«-Steuerelement
  gp 16.10 Die Anzeige eines QuickInfo-Texts
    gp 16.10.1 Methoden des »ToolTip«-Steuerelements
    gp 16.10.2 Aktivierungsdauer des »QuickInfo«-Steuerelements
    gp 16.10.3 Weitere Eigenschaften
  gp 16.11 Das »ListBox«-Steuerelement
    gp 16.11.1 Die Auflistung »ListBox.ObjectCollection«
    gp 16.11.2 Eigenschaften zur Darstellung einer Listbox
    gp 16.11.3 Einfach- und Mehrfachauswahl der Listenelemente
    gp 16.11.4 Programmatischer Zugriff auf Listboxen mit Einfachauswahl
    gp 16.11.5 Benutzerdefiniertes Sortieren der Listenelemente
    gp 16.11.6 Füllen einer Listbox mit »DataSource«
  gp 16.12 Das Steuerelement »CheckedListBox«
  gp 16.13 Die »ComboBox« (Kombinationslistenfeld)
    gp 16.13.1 Ereignisse eines Kombinationslistenfeldes
    gp 16.13.2 Autovervollständigung in einer »ComboBox«


Galileo Computing

16.11 Das »ListBox«-Steuerelement  downtop

Oft ist es erforderlich, dem Benutzer zur Laufzeit eine Auflistung von Elementen in Form von Zeichenfolgen anzubieten. Aus dieser kann er ein oder auch mehrere Elemente auswählen. .NET stellt zu diesem Zweck mehrere Steuerelemente zur Verfügung, von denen die drei wichtigsten

gp  ListBox
gp  CheckedListBox
gp  ComboBox

sind. Alle drei sind aus der gemeinsamen abstrakten Basisklasse ListControl abgeleitet. CheckedListBox ist selbst eine Ableitung von ListBox.

In diesem Abschnitt werden wir uns zunächst der Klasse ListBox widmen und uns daran anschließend den beiden anderen zuwenden.


Galileo Computing

16.11.1 Die Auflistung »ListBox.ObjectCollection«  downtop

Die von einer ListBox verwalteten Listeneinträge sind Elemente einer Auflistung, auf die über Eigenschaft Items zugegriffen werden kann:


Public Overridable ReadOnly Property Items As ObjectCollection

Alle Elemente, die in der Listbox angezeigt werden, sind Mitglieder dieser Auflistung. Wenn wir der Listbox ein Element hinzufügen, ein bestimmtes Element entfernen wollen oder nach einem bestimmten Element suchen, greifen wir auf die Methoden dieser Auflistung zurück.

Hinzufügen von Listenelementen zur Entwicklungszeit

Manchmal ist es möglich, eine ListBox bereits zur Entwicklungszeit vollständig zu füllen. Sie brauchen in diesem Fall im Eigenschaftsfenster nur die Eigenschaft Items zu markieren und können über die Schaltfläche in der Wertespalte einen Dialog öffnen, in dem Sie die Listen-elemente der Reihe nach eintragen.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 16.16     Listenelemente im Eigenschaftsfenster eintragen

Hinzufügen von Listenelementen

Meistens werden Sie allerdings Listen erst zur Laufzeit dynamisch füllen können, um den unterschiedlichen Umgebungsbedingungen gerecht zu werden. Als Mitglieder einer Collection werden Listenelemente über Indizes verwaltet. Das erste Listenelement hat, wie üblich, den Index 0. Drei Methoden ermöglichen das Hinzufügen eines Elements in eine Listbox: Add, AddRange und Insert.

Betrachten wir zuerst die Add-Methode, deren Rückgabewert der Index ist, an dem das Element hinzugefügt worden ist. Das hinzuzufügende Element wird dem Methodenaufruf als Argument übergeben. Dabei müssen wir feststellen, dass der Parameter nicht, wie eigentlich zu erwarten wäre, vom Typ String ist, sondern vom Typ Object. Tatsächlich kann jede beliebige Referenz übergeben werden, angezeigt wird jedoch nur der Rückgabewert der Methode ToString.

Im folgenden Codefragment werden mit der Add-Methode die drei Elemente Franz, Joseph und Uwe hinzugefügt. Das erste Element hat den Index 0, das zweite den Index 1, das dritte den Index 2.


Dim listBox1 As New ListBox
listBox1.Items.Add("Franz")
listBox1.Items.Add("Joseph")
listBox1.Items.Add("Uwe")

Eine Alternative zum sich wiederholenden Add-Aufruf bietet die Methode AddRange, die ein Objekt-Array erwartet:


listBox1.Items.AddRange(New string(){"Franz", "Joseph", "Uwe"})

Soll ein neues Element nicht an das Ende angehängt werden, sondern eine bestimmte Position innerhalb aller Listenelemente einnehmen, hilft die Methode Insert weiter. Dem ersten Parameter wird der gewünschte Index des hinzuzufügenden Elements übergeben, dem zweiten Parameter das Element. Die folgende Anweisung fügt Peter der Listbox mit dem Index 1 an der zweiten Position ein:


listBox1.Items.Insert(1, "Peter")

Ist der Index größer ist als die Anzahl der Elemente in der Listbox, kommt es zu der Ausnahme ArgumentOutOfRangeException.

Listenelemente können mit Sorted auch alphabetisch sortiert werden. Sorted ist standardmäßig auf False eingestellt. Fügen Sie ein Element in eine sortierte Liste ein, wird das neue Element direkt einsortiert.

Steigern der Effizienz beim Hinzufügen von vielen Listenelementen

Die Methode Add hat im Vergleich zur AddRange-Methode den Nachteil, dass die Listbox mit jedem hinzugefügten Listenelement neu aufgebaut wird. Handelt es sich um eine größere Elementanzahl, hat das einen spürbaren Leistungsverlust zur Folge. Besonders deutlich wird der Effekt, wenn die Listenelemente mit Sorted=True sortiert werden sollen. Die Listbox bietet uns Abhilfe: Mit der Methode BeginUpdate lässt sich das Aktualisieren einer Listbox so lange unterdrücken, bis EndUpdate aufgerufen wird. Der Leistungsgewinn kann unter Umständen drastisch sein.

Die folgenden Anweisungen, die beispielsweise beim Klicken auf eine Schaltfläche ausgeführt werden, demonstrieren den Einsatz der beiden Methoden. Für die Dauer des Schleifendurchlaufs wird der Mauscursor als Sanduhr angezeigt, um zu signalisieren, dass die Anwendung eine länger andauernde Operation ausführt.


ListBox1.Sorted = True
ListBox1.BeginUpdate()
Me.Cursor = Cursors.WaitCursor
For i As Integer = 0 To 1000
ListBox1.Items.Add(i)
Next
ListBox1.EndUpdate()
Me.Cursor = Cursors.Default

Den Effekt können Sie sehr gut beobachten, wenn Sie die Methodenaufrufe von BeginUpdate und EndUpdate auskommentieren. Der Aufbau der Listbox benötigt dann ein Vielfaches der Zeit.

Das Löschen eines Elements

Jedes Element in einer Listbox kann durch den in der Listbox angezeigten Text und durch seinen Index beschrieben werden. Das ObjectCollection-Objekt berücksichtigt dies und stellt uns zwei Methoden zur Verfügung, um ein bestimmtes Element aus der Auflistung zu entfernen: Remove und RemoveAt.

Remove erwartet als Argument die Referenz auf ein Objekt und wertet wiederum dessen To-String-Rückgabe aus, RemoveAt nimmt den Index entgegen. Wird ein Element mitten aus der Liste entfernt, verschieben sich alle Nachfolgeindizes, denn eine Auflistung kann niemals eine unbesetzte Position enthalten.


listBox1.Items.Remove("Joseph")

Sollen alle Listenelemente gleichzeitig gelöscht werden, hilft uns die Methode Clear weiter.

Prüfen, ob ein Element in der Listbox enthalten ist

Die Listenelemente einer Listbox sind nicht eindeutig, d. h., dass Sie dasselbe Element auch mehrfach der Auflistung hinzufügen können. Um das zu vermeiden, muss ein hinzuzufügendes Element zuerst daraufhin überprüft werden, ob es bereits eingetragen ist. Die Information darüber liefert die Methode Contains unter Angabe des Objekts. Der Rückgabewert ist vom Typ Boolean und True, wenn das im Parameter genannte Objekt in der Liste enthalten ist.


If (Not ListBox1.Items.Contains("Franz")) Then
ListBox1.Items.Add("Franz")
End If

Den Index eines bestimmten Elements abfragen

Wollen Sie von einem bestimmten Element in der Listbox den Index in der Auflistung erfahren, hilft die Methode IndexOf weiter.


Dim index As Integer = ListBox1.Items.IndexOf("Marokko")

Ist das angegebene Element in der Liste nicht enthalten, ist der Rückgabewert –1.

Den Inhalt der Listbox kopieren

Mit der Methode CopyTo können Sie alle Listbox-Elemente in ein Array kopieren und diesem die Indexposition angeben, ab der die Elemente der Listbox in das Array hineinkopiert werden sollen.

Im folgenden Codefragment wird die Methode dazu benutzt, um bestimmte Elemente der Auflistung in das Array names zu kopieren. Zur Initialisierung des Arrays wird mit der Eigenschaft Count des ObjectCollection-Objekts die Anzahl der in der Listbox enthaltenen Elemente ermittelt, und dazu werden weitere 100 Elemente »zur Reserve« addiert. Der Inhalt von ObjectCollection wird in das Array ab Index 20 kopiert.


Dim names() As String = New String(listBox1.Items.Count + 100)
ListBox1.Items.CopyTo(names, 20)


Galileo Computing

16.11.2 Eigenschaften zur Darstellung einer Listbox  downtop

Jetzt wissen Sie, wie die Elemente einer Listbox in der speziellen Auflistung ObjectCollection verwaltet werden. Wir können uns nun den Eigenschaften der ListBox zuwenden, die in erster Linie dazu dienen, die Darstellung zur Laufzeit festzulegen.

Die Höhe eines Steuerelements kann grundsätzlich beliebig eingestellt werden. Bei einer ListBox könnte das dazu führen, dass ein Listenelement nur teilweise angezeigt wird. Mit der Eigenschaft IntegralHeight wird das vermieden. Diese Eigenschaft hat per Vorgabe den Wert True und bewirkt, dass sich die Höhe der Listbox automatisch so angepasst, dass alle Elemente vollständig angezeigt werden.

Können nicht alle Elemente gleichzeitig angezeigt werden, weil die Komponente zu viele Elemente enthält, wird zur Laufzeit automatisch eine vertikale Bildlaufleiste eingeblendet. Insbesondere bei Listboxen, die zur Laufzeit dynamisch gefüllt werden, möchte man vielleicht auch dann eine Bildlaufleiste anzeigen, wenn die Anzahl der Listenelemente das Steuerelement noch nicht vollständig ausfüllt. Stellen Sie dazu die Eigenschaft ScrollAlwaysVisible=True ein. Überschreitet die Breite des Listeneintrags die Breite der Listbox, ist der nicht sichtbare Teil rechts abgeschnitten. In diesem Fall kann mit der Eigenschaft HorizontalScrollbar eine horizontale Bildlaufleiste angezeigt werden.

Mehrspaltige Listboxen

Unabhängig davon, wie viele Elemente in der Auflistung enthalten sind, ist eine Listbox zunächst immer nur einspaltig. In der folgenden Abbildung enthält die Listbox alle auf dem aktuellen System installierten Schriftarten, die über die Auflistung InstalledFontCollection im Namespace System.Drawing.Text bereitgestellt werden. Um die Listbox beim Laden des Formulars zu füllen, eignet sich das Load-Ereignis oder der Konstruktor der Form:


Private Sub Form1_Load(...) Handles MyBase.Load
Dim myFonts As InstalledFontCollection = _
New InstalledFontCollection()
Dim font() As FontFamily = myFonts.Families
For i As Integer = 0 To Font.Length – 1
ListBox1.Items.Add(font(i).Name)
Next
End Sub

Die Eigenschaft Families eines InstalledFontCollection-Objects liefert ein Array vom Typ FontFamily zurück. Dieser Typ definiert eine Schriftart und veröffentlicht die Eigenschaft Name, die den Bezeichner des Fonts liefert. In einer Schleife wird das Array vom ersten bis zum letzten Element durchlaufen und der Bezeichner der sich jeweils über dem Index im Zugriff befindlichen Schriftart mit der Add-Methode der Auflistung der Listbox hinzugefügt.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 16.17     Anzeige aller installierten Fonts in einer Listbox

Wenn Sie möchten, können Sie die Listenelemente auch auf mehrere Spalten aufteilen. Die Verteilung der Spalten erfolgt dabei so, dass keine vertikalen Bildlaufleisten mehr notwendig sind, sondern nur noch eine horizontale, welche die Navigation zwischen den Spalten ermöglicht. Dazu muss die Eigenschaft MultiColumn=True gesetzt werden. Eine Listbox mit mehreren Spalten sehen Sie in Abbildung 16.18.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 16.18     Mehrspaltige Anzeige in einer Listbox

Die Spaltenbreite können Sie mit ColumnWidth beeinflussen. Aber seien Sie hier vorsichtig. Wählen Sie nämlich eine zu geringe Breite, wird der »überhängende« Teil von der Folgespalte überdeckt. Der Standardwert von 0 legt eine vordefinierte Breite fest, die allerdings nicht die Lesbarkeit aller Elemente sicherstellt.


Galileo Computing

16.11.3 Einfach- und Mehrfachauswahl der Listenelemente  downtop

Belassen Sie es bei der Vorgabe, kann in einer Listbox zur Laufzeit nur ein Eintrag ausgewählt werden. Sie können aber auch festlegen, dass der Anwender gleichzeitig mehrere markieren kann. Dazu müssen Sie die Eigenschaft SelectionMode der Listbox entsprechend festlegen. Diese Eigenschaft bezieht ihre Werte aus der gleichnamigen Enumeration, die vier Mitglieder hat.


Tabelle 16.14     Die Enumeration »SelectionMode«

Member Beschreibung
None Es kann kein Listenelement selektiert werden.
One Es kann ein Listenelement selektiert werden.
MultiSimple Es können mehrere Listenelemente ausgewählt werden.
MultiExtended Es können mehrere Listenelemente ausgewählt werden. Dazu werden die Pfeiltasten, die (Strg)-Taste und die Umschalttaste benutzt.

Bei der Einstellung MultiSimple kann der Anwender mittels Mausklick in beliebiger Reihenfolge die Elemente auswählen, die dann invertiert dargestellt werden. Zudem kann er mit den Pfeiltasten durch die Liste navigieren und mit der Leertaste das fokussierte Element selektieren. Ein Mausklick oder das Drücken der Leertaste auf ein ausgewähltes Element hebt die Markierung des Elements wieder auf.

Die Auswahl MultiExtended ist dann vorteilhaft, wenn der Anwender einen Bereich aufeinander folgender Elemente auswählen soll. Wird ein Element mit der Maus ausgewählt und danach die Umschalttaste gedrückt, sind nach dem Klick auf ein zweites Listenelement alle Elemente zwischen diesen beiden automatisch selektiert. Ähnlich kann auch die Auswahl mit der Tastatur erweitert werden, indem man die Umschalttaste beim Drücken der Pfeiltasten gedrückt hält.


Galileo Computing

16.11.4 Programmatischer Zugriff auf Listboxen mit Einfachauswahl  downtop

Verwenden Sie eine Listbox, die nur die Auswahl eines Elements zulässt, gestaltet sich der Zugriff auf das entsprechende Element anders als bei einer Listbox mit Mehrfachauswahl. Betrachten wir zuerst Listboxen, deren Eigenschaft SelectionMode auf One eingestellt ist.

Am einfachsten ist es, die Eigenschaft Text der Listbox abzurufen, z.  B.:


MessageBox.Show(listBox1.Text)

Nahezu gleichwertig können Sie auch über SelectedItem auf das ausgewählte Listenelement zugreifen.


MessageBox.Show(listBox1.SelectedItem)

Eine dritte Möglichkeit bietet sich mit der Methode Items, welche die Referenz auf ObjectCollection liefert. Dem Index wird das ausgewählte Element übergeben.


MessageBox.Show(listBox1.Items(12))

Die Indexangabe darf natürlich nicht statisch codiert werden, weil sie sich zur Laufzeit abhängig von der Wahl des Anwenders ändert. Hier hilft uns die Eigenschaft SelectedIndex der Listbox weiter, die den Index des ausgewählten Elements bereitstellt. Die Anweisung zur Auswertung der ausgewählten Elemente der Auflistung muss daher lauten:


MessageBox.Show(listBox1.Items(listBox1.SelectedIndex))

SelectedIndex ruft nicht nur den Index des ausgewählten Elements in einer Listbox ab, sondern kann ihn auch festlegen. Das ist für die Entwicklung sehr nützlich, denn standardmäßig wird nach dem Laden und Anzeigen eines Formulars kein Listenelement vorselektiert.

Das Ereignis »SelectedIndexChanged«

In einer Listbox führt sehr häufig das Anklicken eines Listenelements zur sofortigen Verarbeitung. Ein Click-Ereignis bietet das Listenfeld nicht an, stattdessen das Ereignis SelectedIndexChanged. Sehen wir uns das an einem Beispiel an, dessen Form zwei Listboxen enthält (siehe Abbildung 16.19).

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 16.19     Form des Beispiels »ChangeFont«

In der linken wird die Liste aller installierten Fonts angezeigt, in der rechten hat der Anwender die Auswahl der Schriftgröße. Die Änderung der Auswahl in einer der beiden Listboxen bewirkt in einer Textbox die Anpassung der Ausgabezeichenfolge.


' ----------------------------------------------------------
' Beispiel: ...\Kapitel 16\ChangeFont
' ----------------------------------------------------------
Imports System.Drawing.Text
Public Class Form1
Private Sub Form1_Load(...) Handles MyBase.Load
txtTestText.AutoSize = False
Dim myFonts As InstalledFontCollection = _
New InstalledFontCollection()
Dim fonts() As FontFamily = myFonts.Families
' Listbox mit einer Auswahl an Schriftgrößen füllen
For i As Integer = 8 To 24
lstHoehe.Items.Add(i.ToString())
Next
' Listbox mit den installierten Schriftarten füllen
For i As Integer = 0 To fonts.Length – 1
' prüfen, ob der Font das Regular-Format unterstützt
If (fonts(i).IsStyleAvailable(FontStyle.Regular)) Then
lstFonts.Items.Add(fonts(i).Name)
End If
Next
' Vorauswahl in den Listboxen
lstFonts.SelectedIndex = 0
lstHoehe.SelectedIndex = lstHoehe.Items.IndexOf("10")
' Registrierung der Ereignishandler
AddHandler lstFonts.SelectedIndexChanged, _
AddressOf listBox_SelectedIndexChanged
AddHandler lstHoehe.SelectedIndexChanged, _
AddressOf listBox_SelectedIndexChanged
' Schriftart in der Textbox an die Vorauswahl anpassen
listBox_SelectedIndexChanged(Nothing, Nothing)
End Sub
Private Sub listBox_SelectedIndexChanged(...)
txtTestText.Font = New Font(lstFonts.Text,lstHoehe.Text)
End Sub
End Class

Zuerst werden die beiden Listboxen im Load-Ereignishandler der Form gefüllt. Die Elemente, die in der Listbox lstFonts angeboten werden, beziehen wir aus der Auflistung InstalledFontCollection. Wenn Sie jedoch denselben Code zum Füllen der Listbox einsetzen, der weiter oben beschrieben worden ist, werden Sie beim Testen der Anwendung möglicherweise eine unerwartete Feststellung machen: Es kommt zu einem Laufzeitfehler, weil die Zuweisung des in der Listbox markierten Fonts an die Eigenschaft Font der Textbox scheitert. Das ist beispielsweise bei der Schrift Monotype Corsiva der Fall, weil diese Schriftart das Format Regular nicht unterstützt. Um die Exception zu vermeiden und in der Listbox nur anerkannte Schriftarten anzuzeigen, wird vor dem Eintrag in die Listbox der Font zuerst mit der Eigenschaft IsStyleAvailable untersucht:


If (fonts(i).IsStyleAvailable(FontStyle.Regular)) Then
lstFonts.Items.Add(fonts(i).Name)
End If

Weil in einer Listbox nach dem Start der Anwendung zunächst kein Element vorselektiert ist, sollten wir das per Programmcode für beide Listboxen vorgeben:


lstFonts.SelectedIndex = 0

und


lstHoehe.SelectedIndex = lstHoehe.Items.IndexOf("10")

Die Ereignisse SelectedIndexChanged der beiden Listboxen sind mit dem gemeinsamen Handler listBox_SelectedIndexChanged verknüpft, der die Schrift in der Textbox an die Auswahl anpasst.

Beachten Sie bitte unbedingt, dass die Registrierung der beiden Ereignishandler erst erfolgt, nachdem SelectedIndex festgelegt ist. Registrieren Sie vorher, wird der Ereignishandler aufgerufen und verursacht der erste Aufruf des Ereignishandlers einen Laufzeitfehler, weil in der zweiten Listbox noch kein Eintrag markiert ist und sie daher einen ungültigen Wert aufweist.

Im Ereignishandler müssen wir nur die Font-Klasse mit einem passenden Konstruktor instanziieren. Geeignet ist in unserem Fall der Konstruktor, der die Zeichenfolge der Schriftart und die Größe der Schrift erwartet. Das neue Font-Objekt wird der Eigenschaft Font des Textfeldes zugewiesen.


txtTestText.Font = New Font(lstFonts.Text, lstHoehe.Text)

Die letzte Anweisung im Load-Ereignishandler ist der Aufruf der Methode listBox_SelectedIndexChanged. Damit stellen wir sicher, dass nach dem Starten die Schriftart in der Textbox der Voreinstellung in den Listboxen entspricht.

Zugriff auf Listboxen mit Mehrfachauswahl

Wird ein neues ListBox-Steuerelement erzeugt, lässt dies nur die Auswahl eines Elements zu. Die Eigenschaft SelectionMode gestattet die einfache oder erweiterte Mehrfachauswahl. Listenelemente mit Mehrfachauswahl verwalten die ausgewählten Listenelemente in zwei eigenen Auflistungen:

gp  SelectedObjectCollection
gp  SelectedIndexCollection.

Der Zugriff auf die Auflistungen erfolgt über die Eigenschaften SelectedIndices und SelectedItems. Beide ähneln sich in ihrem Verhalten und enthalten die ausgewählten Elemente der Listbox, zu denen sie eine Beziehung entweder über die Referenz oder über den Index herstellen.

Angenommen, »Peter«, »Uwe« und »Willi« sind in dieser Reihenfolge Listenelemente in der Listbox. Sind »Uwe« und »Willi« ausgewählt, enthält die Auflistung SelectedObjectCollection im ihrem ersten, nullindizierten Element den Verweis auf »Uwe«, im zweiten mit 1 indizierten Element den Verweis auf »Willi«. Analog verhält sich die Auflistung SelectedIndexCollection. Sie speichert jedoch nicht die Verweise, sondern den Index aus der Listbox.

Beide Auflistungen weisen die bekannten Eigenschaften und Methoden üblicher Auflistungen auf, beispielsweise Count, Contains, IndexOf sowie einen Indexer, um auf ein bestimmtes Element zuzugreifen.

Sehen wir uns an einem Beispiel an, wie ein Listenelement mit Mehrfachauswahl im Programmcode behandelt wird. Eine Form enthält dazu zwei Listboxen, die beide eine Mehrfachauswahl mit SelectionMode=MultiSimple zulassen (siehe Abbildung 16.20). In der linken wird nach dem Start der Anwendung eine Namensliste angezeigt. Der Benutzer kann mehrere Einträge in der linken Listbox auswählen und durch Klicken auf den oberen Button die ausgewählten Einträge in die rechte Listbox verschieben. Die markierten und verschobenen Einträge müssen danach in der Ursprungslistbox gelöscht werden. Der umgekehrte Vorgang, das Verschieben aus der rechten in die linke Listbox, verläuft analog.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 16.20     Ausgabefenster des Beispiels »MultiSelectListbox«


' ---------------------------------------------------------
' Beispiel: ...\Kapitel 16\MultiSelectListbox
' ---------------------------------------------------------
Public Class Form1
Private Sub btnLeftToRight_Click(...) _
Handles btnLeftToRight.Click
Dim arr(lstleft.SelectedItems.Count – 1) As String
lstleft.SelectedItems.CopyTo(arr, 0)
lstRight.Items.AddRange(arr)
' ausgewählte Elemente in linker Listbox löschen
For i As Integer = lstleft.SelectedItems.Count – 1 To 0 Step –1
lstleft.Items.RemoveAt(lstleft.SelectedIndices(i))
Next
End Sub
Private Sub btnRightToLeft_Click(...) _
Handles btnRightToLeft.Click
Dim arr(lstRight.SelectedItems.Count – 1) As String
lstRight.SelectedItems.CopyTo(arr, 0)
lstleft.Items.AddRange(arr)
' ausgewählte Elemente in rechter Listbox löschen
For i As Integer = lstRight.SelectedItems.Count – 1 To 0 Step –1
lstRight.Items.RemoveAt(lstRight.SelectedIndices(i))
Next
End Sub
Private Sub Form1_Load(...) Handles MyBase.Load
lstleft.Items.AddRange(New String() _
{"Peter", "Uwe", "Michael", _
"Reiner", "Brigitte", "Thea", "Jackie"})
End Sub
End Class

Im Ereignishandler des Load-Ereignisses der Form wird die linke Listbox gefüllt. Die Ereignishandler zu den Click-Ereignissen der Schaltflächen gleichen sich bis auf die Bezeichner, so dass wir uns an dieser Stelle nur mit einem auseinander setzen müssen. Betrachten wir daher nur das Verschieben aus der linken in die rechte Listbox.

Die rechte Listbox soll mit der AddRange-Methode gefüllt werden. AddRange verlangt als Übergabeargument ein Objekt-Array, das wir uns vorher besorgen müssen. Deshalb deklarieren wir zuerst ein Array und initialisieren dieses mit einer Kapazität, die es erlaubt, es mit den ausgewählten Listenelementen aus der Ausgangslistbox füllen zu können. Die Array-Größe resultiert aus der Anzahl der ausgewählten Elemente, die uns die Count-Eigenschaft der Selected-ObjectCollection liefert, deren Referenz wir über SelectedItems als Rückgabewert erhalten.


Dim arr(lstleft.SelectedItems.Count – 1) As String

Mit


lstLeft.SelectedItems.CopyTo(arr, 0)

kopieren wir den Inhalt der Auflistung SelectedObjectCollection in das zuvor deklarierte Array arr, beginnend bei Index 0. Dieses Array übergeben wir der AddRange-Methode.

Nun müssen wir die ausgewählten und bereits verschobenen Listenelemente in der Listbox auch löschen. Der Indexer von SelectedIndexCollection der linken Listbox liefert uns als Rückgabewert die Indizes der ausgewählten Elemente. Diesen Rückgabewert übergeben wir der Methode RemoveAt der Listbox, die in einer Schleife für jedes markierte Listenelement aufgerufen wird:


For i As Integer = lstleft.SelectedItems.Count – 1 To 0 Step –1
lstleft.Items.RemoveAt(lstleft.SelectedIndices(i))
Next

Beachten Sie, die Schleife ausgehend vom höchsten Zählerwert (der der Anzahl der ausgewählten Elemente minus 1 entspricht) bis 0 zu durchlaufen. Damit wird sichergestellt, dass zuerst das markierte Element mit dem höchsten Index aus der Listbox gelöscht wird und erst zum Schluss das mit dem kleinsten Index. Sie vermeiden so Fehler, die sich aus der Verschiebung der Indizes ergeben, denn auch die Listbox lässt keine unbesetzten Indizes zu und verschiebt alle Nachfolgeelemente um eine Position, um eine entstandene Lücke zu schließen. Die Übergabe des Schleifenzählers an SelectedIndices setzt aber eine konstante Zuordnung voraus, um einen logischen Fehler zu vermeiden.


Galileo Computing

16.11.5 Benutzerdefiniertes Sortieren der Listenelemente  downtop

Wenden Sie die Methode Sort auf die Listenelemente einer Listbox an, werden die sichtbaren Einträge alphabetisch sortiert. Eine andere Alternative bietet sich nicht an, da die Methode keine entsprechenden Überladungen hat. Manchmal ist es jedoch erforderlich, eine andere Sortierreihenfolge festzulegen.

Angenommen, in einem ListBox-Objekt sollen Objekte vom Typ Person angezeigt werden.


Public Class Person
Public Zuname As String
Public Vorname As String
Public Alter As Integer
Public Sub New(ByVal zuname As String, _
ByVal vorname As String, ByVal alter As Integer)
Me.Zuname = zuname
Me.Vorname = vorname
Me.Alter = alter
End Sub
Public Overrides Function ToString() As String
Return Me.Zuname & " / " & Me.Vorname & " / " & Me.Alter
End Function
End Class

In der Klasse sind drei Felder öffentlich deklariert. Außerdem ist die Methode ToString überschrieben, weil die Listbox bei der Übergabe von Referenzen immer den Rückgabewert von ToString anzeigt. Die Überschreibung stellt sicher, dass zuerst der Zuname, dann der Vorname und zum Schluss das Alter für jeden Eintrag angezeigt werden.

Wir können uns vorstellen, dass die Elemente in der Listbox nach einem der drei Felder sortiert werden sollen. Die Sorted-Eigenschaft der Listbox leistet das nicht. Wir müssen einen anderen Weg gehen. Dabei hilft uns die überladene Methode Sort der ArrayList weiter, die uns die Möglichkeit gibt, eine Vergleichsklassenreferenz vom Typ IComparer zu übergeben.


Public Overridable Sub Sort(IComparer)

Eine Vergleichsklasse bereitzustellen, ist kein großes Problem. Das haben Sie bereits in Abschnitt 7 gelernt. Eine Hürde ist vielmehr, dass die Methode Sort auf die Referenz einer ArrayList aufgerufen wird, wir jedoch eine Listbox benutzerdefiniert sortieren wollen. Auch über diese Schwierigkeit hilft uns die Klasse ArrayList hinweg: Sie veröffentlicht die statische Methode Adapter, der die Referenz auf ein IList-Objekt übergeben wird.


Public Shared Function Adapter(IList) As ArrayList

Der Zufall will es so, dass die von der Eigenschaft Items zurückgelieferte Referenz vom Typ ObjectCollection genau diese Schnittstelle implementiert. Damit hätten wir alle notwendigen Informationen gesammelt, die uns in die Lage versetzen, eine benutzerdefinierte Sortierung der Listboxelemente anzubieten. Das folgende Beispielprogramm zeigt den Programmcode. Die Form enthält neben einer Listbox auch drei Schaltflächen. Je nachdem, welche Schaltfläche der Benutzer anklickt, wird die Ausgabe in der Listbox nach einem der drei Felder sortiert.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 16.21     Ausgabe des Beispiels »UserDefinedSortedListbox«


' ---------------------------------------------------------
' Beispiel: ...\Kapitel 16\UserDefinedSortedListbox
' ---------------------------------------------------------
' Vergleichsklassen
Public Class CompareZuname
Implements IComparer
Public Function Compare(ByVal pers1 As Object, _
ByVal pers2 As Object) As Integer _
Implements System.Collections.IComparer.Compare
Return pers1.Zuname.CompareTo(pers2.Zuname)
End Function
End Class
Public Class CompareVorname
Implements IComparer
Public Function Compare(ByVal pers1 As Object, _
ByVal pers2 As Object) As Integer _
Implements System.Collections.IComparer.Compare
Return pers1.Vorname.CompareTo(pers2.Vorname)
End Function
End Class
Public Class CompareAlter
Implements IComparer
Public Function Compare(ByVal pers1 As Object, _
ByVal pers2 As Object) As Integer _
Implements System.Collections.IComparer.Compare
Return pers1.Alter.CompareTo(pers2.Alter)
End Function
End Class
' die Form
Public Class Form1
Dim arrList As ArrayList
Private Sub Form1_Load(...) Handles MyBase.Load
Dim persArray() As Person = New Person() { _
New Person("Müller", "Peter", 30), _
New Person("Fischer", "Helmut", 56), _
New Person("Popalowski", "Fred", 22), _
New Person("Heinrich", "Walter", 29), _
New Person("Meier", "Uwe", 12)}
' das Array der Listbox übergeben
ListBox1.Items.AddRange(persArray)
arrList = ArrayList.Adapter(ListBox1.Items)
arrList.Sort(New CompareZuname())
End Sub
' Ereignishandler der drei Schaltflächen
Private Sub Sortieren(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles btnZuname.Click, btnVorname.Click, btnAlter.Click
If (sender Is btnZuname) Then
arrList.Sort(New CompareZuname())
ElseIf (sender Is btnVorname) Then
arrList.Sort(New CompareVorname())
ElseIf (sender Is btnAlter) Then
arrList.Sort(New CompareAlter())
End If
End Sub
End Class


Galileo Computing

16.11.6 Füllen einer Listbox mit »DataSource«  toptop

Mit der Add-Methode des Objekts ObjectCollection lassen sich Listenelemente festlegen. Die .NET-Listbox erlaubt aber noch eine andere Alternative, indem Sie der Eigenschaft DataSource ein Objekt zuweisen. Bedingung ist, dass das Objekt die Schnittstelle IList implementiert. Üblicherweise wird diese Eigenschaft dazu benutzt, um beispielsweise ein ADO.NET-Objekt vom Typ DataSet bekannt zu geben Wir werden uns ADO.NET an späterer Stelle in diesem Buch widmen. Die Vorgehensweise lässt sich aber auch am Beispiel eines ArrayList-Objekts demonstrieren.

Haben Sie der Eigenschaft DataSource der Listbox einen Objektverweis zugewiesen, müssen Sie der Listbox mitteilen, welche Daten sie anzeigen soll. Hierzu übergeben Sie der Eigenschaft DisplayMember eine Zeichenfolge, welche die Eigenschaft angibt, deren Wert als Listenelement angezeigt werden soll. Ein Listenelement kann mit einem bestimmten Wert verknüpft sein. Angenommen, die der Eigenschaft DataSource bekannt gegebene Datenquelle beschreibt verschiedene Wohnungen, deren Beschreibung der Eigenschaft DisplayMember genannt wird, so könnte der mit jedem Listenelement verknüpfte Wert die Miete sein. Übergeben Sie der Eigenschaft ValueMember den Namen der Eigenschaft, welche die Miete liefert. Ausgewertet wird der unter ValueMember eingetragene Wert mit der Eigenschaft Selected-Value.

Machen wir uns das an einem konkreten Beispiel deutlich.


Public Class Wohnung
Private dblWwohnflaeche As Double
Private sngMiete As Single
Private intZimmeranzahl As Integer
Public Sub New(ByVal flaeche As Double, _
ByVal preis As Single, ByVal anzahl As Integer)
dblWwohnflaeche = flaeche
sngMiete = preis
intZimmeranzahl = anzahl
End Sub
Public ReadOnly Property Wohnflaeche()
Get
Return dblWwohnflaeche
End Get
End Property
Public ReadOnly Property Miete()
Get
Return sngMiete
End Get
End Property
Public ReadOnly Property Bezeichnung()
Get
Return intZimmeranzahl.ToString() & "-Zimmer-Wohnung"
End Get
End Property
End Class

In einer Listbox sollen die Bezeichner der Wohnungen angezeigt werden, in zwei Textboxen sowohl der Mietpreis als auch die Wohnfläche des ausgewählten Listenelements. Über die Add-Methode dürfte die Lösung keine Probleme bereiten, wir wollen aber nun alternativ die drei Eigenschaften DataSource, DisplayMember und ValueMember im Einsatz sehen.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 16.22     Anzeigeformular des Beispiels »DataSourcePropertyDemo«


' ---------------------------------------------------------
' Beispiel: ...\Kapitel 16\DataSourcePropertyDemo
' ---------------------------------------------------------
Public Class Form1
Dim wohnungen As New ArrayList
Private Sub Form1_Load(...) Handles MyBase.Load
wohnungen.Add(New Wohnung(25, 300, 1))
wohnungen.Add(New Wohnung(54, 470, 2))
wohnungen.Add(New Wohnung(87, 729, 4))
wohnungen.Add(New Wohnung(60, 650, 2))
wohnungen.Add(New Wohnung(75, 680, 3))
ListBox1.DataSource = wohnungen
ListBox1.DisplayMember = "Bezeichnung"
ListBox1.ValueMember = "Miete"
ListBox1.SelectedIndex = 1
End Sub
Private Sub ListBox1_SelectedIndexChanged(...) _
Handles ListBox1.SelectedIndexChanged
txtMiete.Text = ListBox1.SelectedValue.ToString()
txtFlaeche.Text = _
ListBox1.SelectedItem.Wohnflaeche.ToString()
End Sub
End Class

DataSource erwartet die Referenz auf ein IList-implementierendes Objekt. Hier ist es ein ArrayList-Objekt mit der Bezeichnung wohnungen, dem mehrere Wohnung-Objekte hinzugefügt werden. Anschließend wird das ArrayList-Objekt der DataSource-Eigenschaft übergeben. Im ListBox-Steuerelement sollen die Inhalte der Eigenschaft Bezeichnung angezeigt werden. Das erreichen wir mit der Zuweisung:


listBox1.DisplayMember = "Bezeichnung"

Weil ein Wohnung-Objekt zwei weitere Eigenschaften hat, steht es uns frei, eine der beiden zu wählen und der Eigenschaft ValueMember zu übergeben. Die Entscheidung ist in diesem Beispiel auf Miete gefallen.


listBox1.ValueMember = "Miete"

ValueMember eine Eigenschaft anzugeben, ist optional.

Wählt der Anwender ein Listenelement aus, wird das Ereignis SelectedIndexChanged ausgelöst. In der Textbox txtMiete zeigen wir den Mietpreis des gewählten Listenelements an, indem wir die Eigenschaft SelectedValue auswerten, die uns den Wert der unter ValueMember genannten Eigenschaft liefert. Die Wohnfläche in der Textbox txtFlaeche kann nur durch Auswertung von SelectedItem mit anschließender Konvertierung in den Typ Wohnung erfolgen.


Hinweis

Beachten Sie bitte, dass eine Listbox nicht mit Sorted sortiert werden kann, wenn die Eigenschaft DataSource zum Füllen benutzt wird.


 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de